package app.auto.designer.view;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.GridLayout;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.Map;
import java.util.Stack;
import java.util.TreeMap;

import app.auto.designer.R;
import app.auto.runner.base.action.ViewInflater;
import app.auto.runner.base.intf.MapBuilder;
import app.auto.runner.base.utility.ToastUtil;

public class Parser {
    Activity aty;
    public ProduceView root;
    View getResult;


    public static Parser withActivity(Activity paty) {
        Parser parser = new Parser();
        parser.aty = paty;
        return parser;
    }

    public Parser parse(String stringreader, ViewGroup vg, View v) throws XmlPullParserException, IOException, IllegalAccessException, NoSuchFieldException {
        View view = null;
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XmlPullParser parser = factory.newPullParser();
        InputStream is = new ByteArrayInputStream(stringreader.getBytes());

        parser.setInput(is, "utf-8");
        parser.setInput(new StringReader(stringreader));
        return parse(parser, vg, v);
    }

    boolean tosettag = true;

    public Parser setTosettag(boolean tosettag) {
        this.tosettag = tosettag;
        return this;
    }

    public Parser parse(XmlPullParser parser, ViewGroup vg, View view) throws XmlPullParserException, IOException, IllegalAccessException, NoSuchFieldException {
//if(view!=null&&vg!=null){
//    if(view.getParent()==vg){
//        ProduceView produceView = new ProduceView(parser, vg, view, "").setSetTosettag(tosettag).invoke();
//        if (produceView.is()) return this;
//    }
//}
        int eventType = 0;// 循环取出数据
        String t = "";
        eventType = parser.getEventType();
        try {
            parser.nextTag();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Stack<ViewGroup> stack = new Stack<ViewGroup>();
        View root = null;
        String name = null;
        while ((eventType = parser.getEventType()) != XmlPullParser.END_DOCUMENT) {
            name = parser.getName();
            if (name == null) {
                if (eventType == XmlPullParser.END_TAG) {
                    if (view instanceof ViewGroup) {


                        if (stack.size() > 1) {
                            ViewGroup now = stack.pop();
                            stack.peek().addView(now);
                        } else {
                            stack.empty();
                        }

                    }
                }
                parser.next();
                continue;
            }
            if (eventType == XmlPullParser.START_DOCUMENT || eventType == XmlPullParser.START_TAG) {


                ProduceView produceView = new ProduceView(parser, vg, view, t).setSetTosettag(tosettag).invoke();
                if (produceView.is()) continue;
                view = produceView.getView();
                if (root == null) {
                    root = view;
                    this.getResult = root;
                    this.root = produceView;
                }
                t = produceView.getT();
                if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
                    stack.push((ViewGroup) view);
                } else {
                    if (stack.size() > 0) {
                        stack.peek().addView(view);
                    }
                }
            } else if (eventType == XmlPullParser.END_TAG) {
                if (name.contains(".")) {

                } else {
                    name = "android.widget." + name;
                }
                View cr = null;
                try {

                    cr = (View) Class.forName(name)
                            .getConstructor(Context.class)
                            .newInstance(aty);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (cr instanceof ViewGroup) {

                    if (stack.size() > 1) {
                        ViewGroup now = stack.pop();
                        stack.peek().addView(now);
                    } else {
                        stack.empty();
                    }

                }
            }
            parser.next();
            view = null;
        }

        if (vg != null) {
            vg.addView(root);
        }
        return this;
    }

    public View getView() {
        return getResult;
    }

    public ProduceView getProduceView() {
        return root;
    }

    public void setPadding(View view, int ppl, int ppr, int ppt, int ppb) {
        int pl = view.getPaddingLeft();
        int pr = view.getPaddingRight();
        int pt = view.getPaddingTop();
        int pb = view.getPaddingBottom();
        pl = ppl != -1 ? ppl : pl;
        pr = ppr != -1 ? ppr : pr;
        pt = ppt != -1 ? ppt : pt;
        pb = ppb != -1 ? ppb : pb;
        view.setPadding(pl, pt, pt, pb);
    }

    public static float dip2px(Context context, float dipValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (dipValue * scale + 0.5f);
    }

    float dimenToPixel(String dimen) {
        if (dimen.endsWith("dip")) {
            return dip2px(aty, Float.parseFloat(dimen.substring(0, dimen.length() - 3)));
        } else if (dimen.endsWith("dp"))
            return DynamicHelper.dpToPx(Float.parseFloat(dimen.substring(0, dimen.length() - 2)));
        else if (dimen.endsWith("sp"))
            return DynamicHelper.spToPx(Float.parseFloat(dimen.substring(0, dimen.length() - 2)));
        else if (dimen.endsWith("px"))
            return Integer.parseInt(dimen.substring(0, dimen.length() - 2));
        else if (dimen.endsWith("%"))
            return (int) (Float.parseFloat(dimen.substring(0, dimen.length() - 1)) / 100f * DynamicHelper.deviceWidth());
        else if (dimen.equalsIgnoreCase("match_parent"))
            return ViewGroup.LayoutParams.MATCH_PARENT;
        else if (dimen.equalsIgnoreCase("wrap_content"))
            return ViewGroup.LayoutParams.WRAP_CONTENT;
        else
            return Integer.parseInt(dimen);
    }

    public class ProduceView {
        private boolean myResult;
        private XmlPullParser parser;
        private ViewGroup vg;
        private View view;
        private String t;
        Map attrs = new TreeMap();

        public Map getAttrs() {
            return attrs;
        }

        public boolean setTosettag;

        public ProduceView setSetTosettag(boolean setTosettag) {
            this.setTosettag = setTosettag;
            return this;
        }

        public ProduceView(XmlPullParser parser, ViewGroup vg, View view, String t) {
            this.parser = parser;
            this.vg = vg;
            this.view = view;
            this.t = t;
        }

        boolean is() {
            return myResult;
        }

        public View getView() {
            return view;
        }

        public String getT() {
            return t;
        }

        public ProduceView invoke() throws IllegalAccessException, NoSuchFieldException {
            String name = parser.getName();
            t = "";
            if (name.contains(".")) {

            } else {
                name = "android.widget." + name;
            }

            try {
                if (view == null) {

                    view = (View) Class.forName(name)
                            .getConstructor(Context.class)
                            .newInstance(aty);
                } else {
                    if (!name.equals(view.getClass().getName())) {
                        throw new RuntimeException("as params, 'name' is not same as 'view'.getClass().getName()");
                    }

                }
                if (vg != null) {
                    MapBuilder ps = MapBuilder.build().add("ViewGroup", new ViewGroup.MarginLayoutParams(-2, -2))
                            .add("FrameLayout", new FrameLayout.LayoutParams(-2, -2))
                            .add("RelativeLayout", new RelativeLayout.LayoutParams(-2, -2))
                            .add("LinearLayout", new LinearLayout.LayoutParams(-2, -2))
                            .add("GridLayout", new GridLayout.LayoutParams());
                    view.setLayoutParams((ViewGroup.MarginLayoutParams) ps.get().get(vg.getClass().getSimpleName()));

                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            t += "\n";
            for (int i = 0; i < parser.getAttributeCount(); i++) {
                String n = parser.getAttributeName(i);
                n = n.replace("android:", "");
                String v = parser.getAttributeValue(i);
                t += "android:" + n + "=\"" + v + "\"\n";
                attrs.put(n, v);
                if (n.equals("layout_width") || n.equals("layout_height")) {
                    if (vg != null) {
                        float px;
                        if (v.equals("fill_parent") || v.equals("match_parent")) {
                            px = -1;
                        } else if (v.equals("wrap_content")) {
                            px = -2;
                        } else {
                            px = dimenToPixel(v);

                        }
                        Object lps = ((ViewGroup.MarginLayoutParams) view.getLayoutParams());
                        lps.getClass().getField(n.replace("layout_", "")).set(lps, new Float(px + "").intValue());
                    }
                } else if (n.contains("src")) {
                    if (v.contains("@drawable")) {

                    }
                } else if (n.contains("background")) {
                    if (view.getTag(R.id.uiflag) != null) {
                        if (view.getTag(R.id.uiflag).toString().equals("true")) {
                            view.setBackground(null);
                            view.setTag(R.id.uiflag, "rmbackground");
                        }
                    }
                    if (v.contains("@color")) {

                    } else if (v.contains("@drawable")) {

                    } else if (v.contains("#")) {
                        int color = Color.parseColor(v);
                        view.setBackgroundColor(color);
                    } else /* */ {
                        ToastUtil.live(aty).toast(v);
                    }
                } else if (n.contains("padding")) {

                    if (n.contains("@dimension")) {

                    } else {
                        int p = (int) dimenToPixel(v);
                        if (n.toLowerCase().contains("left")) {
                            setPadding(view, p, -1, -1, -1);
                        } else if (n.toLowerCase().contains("top")) {
                            setPadding(view, -1, p, -1, -1);
                        } else if (n.toLowerCase().contains("right")) {
                            setPadding(view, -1, -1, p, -1);
                        } else {
                            setPadding(view, -1, -1, -1, p);
                        }

                    }
                } else if (n.contains("layout_weight")) {
                    if (view instanceof LinearLayout) {
                        if (view.getLayoutParams() != null) {
                            ((LinearLayout.LayoutParams) ((LinearLayout) view).getLayoutParams()).weight = Integer.parseInt(n);

                        }
                    }
                } else if (n.contains("layout_margin")) {
                    if (vg != null) {
                        if (v.contains("@dimension")) {

                        } else {
                            int p = (int) dimenToPixel(v);
                            if (n.toLowerCase().contains("left")) {
                                ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = p;
                            } else if (n.toLowerCase().contains("top")) {
                                ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin = p;
                            } else if (n.toLowerCase().contains("right")) {
                                ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = p;
                            } else {
                                ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).bottomMargin = p;
                            }

                        }
                    }
                } else if (n.contains("alignParent") && vg != null && vg instanceof RelativeLayout) {
                    if (view.getLayoutParams() == null) {
                        view.setLayoutParams(new RelativeLayout.LayoutParams(-1, -1));
                    }
                    MapBuilder mb = MapBuilder.build().add("left", RelativeLayout.ALIGN_PARENT_LEFT)
                            .add("top", RelativeLayout.ALIGN_PARENT_TOP)
                            .add("right", RelativeLayout.ALIGN_PARENT_RIGHT)
                            .add("bottom", RelativeLayout.ALIGN_PARENT_BOTTOM)
                            .add("start", RelativeLayout.ALIGN_PARENT_START)
                            .add("end", RelativeLayout.ALIGN_PARENT_END);
                    Integer align = (Integer) mb.get().get(n.toLowerCase().replace("layout_alignparent", ""));
                    if (align != null) {
                        if (v.equals("true")) {
                            ((RelativeLayout.LayoutParams) view.getLayoutParams()).addRule(align);
                        } else {
                            ((RelativeLayout.LayoutParams) view.getLayoutParams()).removeRule(align);
                        }
                    }
                } else if (n.contains("layout_center")) {
                    if (view.getLayoutParams() == null) {
                        view.setLayoutParams(new RelativeLayout.LayoutParams(-1, -1));
                    }
                    MapBuilder mb = MapBuilder.build().add("vertical", RelativeLayout.CENTER_VERTICAL)
                            .add("horizontal", RelativeLayout.CENTER_HORIZONTAL)
                            .add("inparent", RelativeLayout.CENTER_IN_PARENT);
                    Integer align = (Integer) mb.get().get(n.toLowerCase().replace("layout_center", ""));
                    if (align != null) {
                        if (v.equals("true")) {
                            ((RelativeLayout.LayoutParams) view.getLayoutParams()).addRule(align);
                        } else {
                            ((RelativeLayout.LayoutParams) view.getLayoutParams()).removeRule(align);
                        }
                    }
                } else if (n.equals("gravity")) {
                    MapBuilder mb = MapBuilder.build();
                    mb.add("center_horizontal", Gravity.CENTER_HORIZONTAL)
                            .add("clip_vertical", Gravity.CLIP_VERTICAL)
                            .add("end", Gravity.END)
                            .add("right", Gravity.RIGHT)
                            .add("fill_vertical", Gravity.FILL_VERTICAL)
                            .add("bottom", Gravity.BOTTOM)
                            .add("fill", Gravity.FILL)
                            .add("center_vertical", Gravity.CENTER_VERTICAL)
                            .add("left", Gravity.LEFT)
                            .add("top", Gravity.TOP)
                            .add("clip_horizontal", Gravity.CLIP_HORIZONTAL)
                            .add("fill_horizontal", Gravity.FILL_HORIZONTAL)
                            .add("center", Gravity.CENTER);
                    String[] attrs = v.split("\\|");
                    Integer values = null;
                    for (String a : attrs) {
                        Integer gravity = (Integer) mb.get().get(a.toLowerCase());
                        if (values == null) {
                            values = gravity;
                        } else {
                            if (gravity != null) {
                                values |= gravity.intValue();
                            }
                        }
                    }
                    if (values != null && view instanceof TextView) {
                        ((TextView) view).setGravity(values);
                    }
                } else if (n.contains("layout_gravity")) {
                    MapBuilder mb = MapBuilder.build();
                    mb.add("strat", Gravity.START)
                            .add("center_horizontal", Gravity.CENTER_HORIZONTAL)
                            .add("clip_vertical", Gravity.CLIP_VERTICAL)
                            .add("end", Gravity.END)
                            .add("right", Gravity.RIGHT)
                            .add("fill_vertical", Gravity.FILL_VERTICAL)
                            .add("bottom", Gravity.BOTTOM)
                            .add("fill", Gravity.FILL)
                            .add("center_vertical", Gravity.CENTER_VERTICAL)
                            .add("left", Gravity.LEFT)
                            .add("top", Gravity.TOP)
                            .add("clip_horizontal", Gravity.CLIP_HORIZONTAL)
                            .add("fill_horizontal", Gravity.FILL_HORIZONTAL)
                            .add("center", Gravity.CENTER);
                    String[] attrs = v.split("\\|");
                    Integer values = null;
                    for (String a : attrs) {
                        Integer gravity = (Integer) mb.get().get(a.toLowerCase());

                        if (values == null) {
                            values = gravity;
                        } else {
                            if (gravity != null) {
                                values |= gravity.intValue();
                            }
                        }
                    }
                    if (values != null && view instanceof LinearLayout) {
                        LinearLayout.LayoutParams ll = (LinearLayout.LayoutParams) view.getLayoutParams();
                        ll.gravity = values;
                    }

                } else if (n.equals("text")) {

                    if (view instanceof TextView) {
                        ((TextView) view).setText(v);
                    }

                } else if (n.toLowerCase().equals("textcolor")) {

                    if (view instanceof TextView) {
                        if (v.contains("@color")) {

                        } else
                            ((TextView) view).setTextColor(Color.parseColor(v));
                    }

                } else if (n.toLowerCase().equals("textsize")) {
                    if (v.contains("@dimension")) {

                    }
                    if (view instanceof TextView) {
                        if (v.contains("dip")) {
                            ((TextView) view).setTextSize(TypedValue.COMPLEX_UNIT_DIP, Float.parseFloat(v.substring(0, v.length() - 3)));
                        } else {
                            ((TextView) view).setTextSize(dimenToPixel(v));
                        }
                    }

                } else if (n.toLowerCase().equals("lines")) {
                    if (v.contains("@integer")) {

                    } else {
                        if (view instanceof TextView) {
                            ((TextView) view).setLines(Integer.parseInt(v));
                        }
                    }

                } else if (n.toLowerCase().equals("maxLines")) {
                    if (v.contains("@integer")) {

                    } else {
                        if (view instanceof TextView) {
                            ((TextView) view).setMaxLines(Integer.parseInt(v));
                        }
                    }

                } else if (n.toLowerCase().equals("ellipsize")) {
                    if (v.contains("@integer")) {

                    } else {
                        if (view instanceof TextView) {
                            MapBuilder mb = MapBuilder.build().add("end", TextUtils.TruncateAt.END)
                                    .add("marquee", TextUtils.TruncateAt.MARQUEE)
                                    .add("middle", TextUtils.TruncateAt.MIDDLE)
//                                    .add("none", TextUtils.TruncateAt.valueOf("NONE"))
                                    .add("start", TextUtils.TruncateAt.START);
                            ((TextView) view).setEllipsize((TextUtils.TruncateAt) mb.get().get(v));
                        }
                    }

                } else if (n.toLowerCase().equals("orientation")) {

                    if (view instanceof LinearLayout) {
                        MapBuilder mb = MapBuilder.build().add("vertical", LinearLayout.VERTICAL)
                                .add("horizontal", LinearLayout.HORIZONTAL);
                        ((LinearLayout) view).setOrientation((Integer) mb.get().get(v));
                    }
                } else if (n.toLowerCase().equals("id")) {
                    view.setTag(R.id.tag_id, v.replace("@+id/", "@id/"));

                } else if (n.toLowerCase().contains("layout_to") || n.toLowerCase().equals("layout_above") || n.toLowerCase().equals("layout_below")) {

                } else if (n.toLowerCase().equals("tag")) {
                    ViewInflater.tagrate(view, v, view.getContext());
                } else if (n.equals("numColumns")) {
                    ((GridView) view).setNumColumns(Integer.parseInt(v));
                }

            }
            if (setTosettag) {

                t = "<" + parser.getName() + "  xmlns:android=\"http://schemas.android.com/apk/res/android\"" + t + "/>";
                if (t.contains("xml:")) {
                    int j = 0;
                    j++;
                }
                view.setTag(R.id.xml, t);
            }
            myResult = false;
            return this;
        }
    }
}
